<template>
  <PageCard title="AI手相分析" titleEnglish="AI Palm Reading">
    <div class="palm-reading-container">
      <n-grid :cols="12" :x-gap="24" :y-gap="24">
        <n-grid-item :span="uploadCardSpan">
          <n-card title="上传手掌照片" embedded :bordered="false">
            <n-space vertical>
              <n-alert type="info" :bordered="false">
                请上传清晰的手掌照片，确保掌纹清晰可见，光线充足。
              </n-alert>

              <div v-if="!imageUrl" class="upload-area">
                <n-upload
                  :action="uploadApi"
                  :max="1"
                  accept="image/*"
                  @finish="handleUploadFinish"
                  @before-upload="beforeUpload"
                  :show-file-list="false"
                  @error="handleUploadError"
                  :default-upload="false"
                  :disabled="uploading"
                >
                  <n-upload-dragger :style="uploadDraggerStyle">
                    <div v-if="!uploading">
                      <div style="margin-bottom: 16px">
                        <n-icon size="48" :depth="3">
                          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path fill="currentColor" d="M9 16h6v-6h4l-7-7l-7 7h4v6zm-4 2h14v2H5v-2z"/>
                          </svg>
                        </n-icon>
                      </div>
                      <n-text style="font-size: 16px;">
                        点击或拖拽上传手掌照片
                      </n-text>
                      <n-p depth="3" style="margin: 12px 0">
                        支持 JPG / PNG / JPEG 格式
                      </n-p>
                      <n-button type="primary" size="large" style="margin-top: 16px">
                        <template #icon>
                          <n-icon>
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                              <path fill="currentColor" d="M9 16h6v-6h4l-7-7l-7 7h4v6zm-4 2h14v2H5v-2z"/>
                            </svg>
                          </n-icon>
                        </template>
                        选择文件上传
                      </n-button>
                    </div>
                    <div v-else class="upload-loading">
                      <n-spin size="large" :show="true">
                        <template #description>
                          <n-text :style="{ fontSize: isMobile ? '14px' : '16px' }">
                            文件上传中，请稍候...
                          </n-text>
                        </template>
                      </n-spin>
                    </div>
                  </n-upload-dragger>
                </n-upload>
              </div>
              <div v-else class="uploaded-image-preview">
                <n-image
                  :src="imageUrl"
                  :img-props="{ style: 'width: 100%; height: auto; max-height: 400px; object-fit: contain;' }"
                />
                <n-button
                  class="remove-button"
                  type="error"
                  size="small"
                  circle
                  quaternary
                  @click.stop="handleRemove"
                >
                  <template #icon>
                    <n-icon size="20">
                      <CloseCircle />
                    </n-icon>
                  </template>
                </n-button>
              </div>

              <n-button
                type="primary"
                block
                size="large"
                :disabled="!imageUrl"
                :loading="analyzing"
                @click="analyzeImage"
              >
                开始AI分析
              </n-button>
            </n-space>
          </n-card>
        </n-grid-item>

        <n-grid-item :span="resultCardSpan">
          <n-card title="分析结果" embedded :bordered="false">
            <div v-if="!analysisResult && !isAnalyzing" class="empty-result">
              <n-empty description="上传照片后点击分析按钮查看结果" />
            </div>

            <div v-else-if="isAnalyzing && !analysisResult" class="loading-state">
              <n-spin size="large" :show="true">
                <template #description>
                  正在分析中，请稍候...
                </template>
              </n-spin>
            </div>

            <div v-else class="analysis-result">
              <n-space vertical>
                <div class="streaming-result" :class="{ 'is-streaming': isAnalyzing }" v-if="analysisResult">
                  <MarkdownRenderer :content="analysisResult" />
                </div>

                <n-divider v-if="!isAnalyzing" />

                <n-space v-if="!isAnalyzing">
                  <n-button @click="saveResult" type="info">
                    保存结果
                  </n-button>
                  <n-button @click="resetAnalysis" type="default">
                    重新分析
                  </n-button>
                </n-space>
              </n-space>
            </div>
          </n-card>
        </n-grid-item>
      </n-grid>

    </div>
    <n-divider />
    <UsageGuide
      :title="usageGuideConfig.title"
      :steps="usageGuideConfig.steps"
      :tips="usageGuideConfig.tips"
      :example="usageGuideConfig.example"
    />
  </PageCard>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import {
  NGrid,
  NGridItem,
  NCard,
  NUpload,
  NUploadDragger,
  NButton,
  NIcon,
  NText,
  NSpace,
  NAlert,
  NEmpty,
  NImage,
  NDivider,
  NP,
  NSpin,
  UploadFileInfo,
  useMessage
} from 'naive-ui'
import { CloseCircle } from '@vicons/ionicons5'
import PageCard from '@/components/PageCard.vue'
import UsageGuide from '@/components/UsageGuide.vue'
import MarkdownRenderer from '@/components/MarkdownRenderer.vue'
import { uploadApi, getUpToken } from '@/api/oss'
import { PalmReadingApi } from '@/api/entertainment/palmReading'
import { SSEClient } from '@/utils/sse'
import { generateOssKey, getOssUrl } from '@/utils/oss'
import { useBreakpoint } from '@/utils/responsive-helper'

const message = useMessage()

// 响应式布局
const { isMobile } = useBreakpoint()

// 根据屏幕大小计算 span
const uploadCardSpan = computed(() => isMobile.value ? 12 : 6)
const resultCardSpan = computed(() => isMobile.value ? 12 : 6)

// 上传区域样式
const uploadDraggerStyle = computed(() => ({
  width: '100%',
  minHeight: isMobile.value ? '250px' : '300px'
}))

const imageUrl = ref<string>('')
const analyzing = ref(false)
const analysisResult = ref<string>('')
const isAnalyzing = ref(false)
const uploading = ref(false) // 新增：文件上传状态

// UsageGuide configuration
const usageGuideConfig = {
  title: '使用说明',
  steps: [
    '拍摄或选择一张清晰的手掌照片',
    '确保照片中掌纹清晰可见，光线充足',
    '点击上传按钮或拖拽文件到上传区域',
    '上传成功后点击\'开始AI分析\'按钮',
    '等待AI分析完成，查看详细的手相解读结果'
  ],
  tips: [
    '建议使用自然光拍摄，避免过强或过暗的光线',
    '手掌平放，五指自然张开，确保掌纹完整',
    '支持JPG、PNG、JPEG格式',
    'AI分析仅供娱乐参考，不代表科学依据'
  ],
  example: '拍摄要求：手掌平放在纯色背景上，掌心朝上，自然光线下拍摄'
}

const beforeUpload = (data: {
  file: UploadFileInfo
  fileList: UploadFileInfo[]
}) => {
  const file = data.file.file
  if (!file) return false

  const isImage = file.type.startsWith('image/')
  if (!isImage) {
    message.error('请上传图片文件')
    return false
  }

  // 改为使用 OSS 直传
  handleOssUpload(data)
  return false
}

// 直传 OSS 的上传处理函数
const handleOssUpload = async (data: {
  file: UploadFileInfo
  fileList: UploadFileInfo[]
}) => {
  const file = data.file.file
  if (!file) return

  uploading.value = true // 使用独立的上传状态

  try {
    // 1. 获取上传 token
    const token = await getUpToken()
    
    // 2. 生成唯一的文件 key
    const key = generateOssKey(file, 'palm-reading')
    
    // 3. 构建上传表单数据
    const formData = new FormData()
    formData.append('key', key)
    formData.append('token', token)
    formData.append('file', file)
    
    // 4. 直接上传到七牛云
    const uploadUrl = import.meta.env.VITE_OSS_UPLOAD_URL
    const response = await fetch(uploadUrl, {
      method: 'POST',
      body: formData
    })

    if (!response.ok) {
      throw new Error(`上传失败: ${response.status}`)
    }

    const result = await response.json()
    
    // 5. 拼接完整的文件 URL
    const fullUrl = getOssUrl(result.key || key)
    imageUrl.value = fullUrl
    message.success('上传成功')
    
  } catch (error) {
    console.error('OSS upload error:', error)
    message.error('上传失败：' + (error instanceof Error ? error.message : '未知错误'))
  } finally {
    uploading.value = false // 上传完成后重置状态
  }
}

// 保留原有的服务器上传函数作为备用
const handleUploadAction = async (data: {
  file: UploadFileInfo
  fileList: UploadFileInfo[]
}) => {
  const file = data.file.file
  if (!file) return

  const formData = new FormData()
  formData.append('file', file)

  uploading.value = true // 使用独立的上传状态

  try {
    const response = await fetch(uploadApi as string, {
      method: 'POST',
      body: formData
    })

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }

    const result = await response.json()

    if (result.code === 200) {
      imageUrl.value = result.data
      message.success('上传成功')
    } else {
      message.error(result.message || '上传失败')
    }
  } catch (error) {
    console.error('Upload error:', error)
    message.error('上传失败：请确保后端服务已启动')
  } finally {
    uploading.value = false // 上传完成后重置状态
  }
}

const handleUploadError = (error: Error) => {
  console.error('Upload component error:', error)
  message.error('上传组件错误：' + error.message)
}

const handleUploadFinish = ({
  file,
  event
}: {
  file: UploadFileInfo
  event?: ProgressEvent
}) => {
  try {
    const response = (event?.currentTarget as XMLHttpRequest)?.response
    if (response) {
      const parse = JSON.parse(response)
      if (parse.code === 200) {
        file.url = parse.data
        imageUrl.value = parse.data
        message.success('上传成功')
      } else {
        message.error(parse.message || '上传失败，请检查服务器是否正常运行')
      }
    } else {
      message.error('上传失败：服务器无响应')
    }
  } catch (error) {
    console.error('Upload error:', error)
    message.error('上传失败：请确保后端服务已启动')
  }
  return file
}

const handleRemove = () => {
  imageUrl.value = ''
  analysisResult.value = ''
  isAnalyzing.value = false
  return true
}

const analyzeImage = async () => {
  if (!imageUrl.value) {
    message.warning('请先上传手掌照片')
    return
  }

  analyzing.value = true
  isAnalyzing.value = true

  try {
    const reader = await PalmReadingApi.analyzePalm({ imageUrl: imageUrl.value })

    await SSEClient.processStream(reader, {
      targetRef: analysisResult,
      clearBeforeStart: true,
      onError: (err) => {
        message.error(err.message || '分析失败，请重试')
      },
      onComplete: () => {
        isAnalyzing.value = false
        message.success('分析完成')
      }
    })
  } catch (error: any) {
    message.error('分析出错，请稍后重试')
    console.error(error)
    isAnalyzing.value = false
  } finally {
    analyzing.value = false
  }
}

const saveResult = () => {
  if (!analysisResult.value) return

  // 直接保存Markdown格式的内容
  const blob = new Blob([analysisResult.value], { type: 'text/markdown' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `手相分析结果_${new Date().toLocaleDateString()}.md`
  a.click()
  URL.revokeObjectURL(url)

  message.success('保存成功')
}

const resetAnalysis = () => {
  imageUrl.value = ''
  analysisResult.value = ''
  isAnalyzing.value = false
}

</script>

<style scoped>
.palm-reading-container {
  padding: 20px;
}

/* 移动端样式优化 */
@media (max-width: 768px) {
  .palm-reading-container {
    padding: 12px;
  }
}

.empty-result {
  min-height: 400px;
  display: flex;
  align-items: center;
  justify-content: center;
}

@media (max-width: 768px) {
  .empty-result {
    min-height: 300px;
  }
}

.loading-state {
  min-height: 400px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
}

@media (max-width: 768px) {
  .loading-state {
    min-height: 300px;
  }
}


.analysis-result {
  animation: fadeIn 0.5s ease-in;
}

.streaming-result {
  min-height: 200px;
  max-height: 500px;
  overflow-y: auto;
  padding: 16px;
  background: #fafafa;
  border-radius: 8px;
  border: 1px solid #e4e4e7;

  .dark & {
    background: rgba(255, 255, 255, 0.03);
    border-color: rgba(255, 255, 255, 0.1);
  }
}

@media (max-width: 768px) {
  .streaming-result {
    min-height: 150px;
    max-height: 400px;
    padding: 12px;
  }
}

/* 优化Markdown内容显示 */
.streaming-result :deep(.markdown-body) {
  padding: 4px;
  background: transparent;
}

/* 流式渲染时的光标效果 */
.streaming-result.is-streaming::after {
  content: '▋';
  animation: blink 1s infinite;
  color: #ff69b4;
  font-weight: bold;
}

@keyframes blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}


@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

:deep(.n-upload-dragger) {
  background: #fafafa;
  border: 2px dashed #d9d9d9;
  transition: all 0.3s ease;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;

  .dark & {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.2);
  }

  &[data-disabled="true"] {
    cursor: wait;
    opacity: 1;
    background: #f8f8f8;
    
    .dark & {
      background: rgba(255, 255, 255, 0.02);
    }
  }
}

:deep(.n-upload-dragger:hover) {
  border-color: #40a9ff;
  background: #f5f5f5;

  .dark & {
    background: rgba(255, 255, 255, 0.08);
    border-color: #40a9ff;
  }

  &[data-disabled="true"] {
    border-color: #d9d9d9;
    background: #f8f8f8;
    
    .dark & {
      background: rgba(255, 255, 255, 0.02);
      border-color: rgba(255, 255, 255, 0.2);
    }
  }
}


.uploaded-image-preview {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 300px;
  background: linear-gradient(135deg, #f8f8f8 0%, #f0f0f0 100%);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);

  .dark & {
    background: linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.04) 100%);
  }
}

@media (max-width: 768px) {
  .uploaded-image-preview {
    min-height: 250px;
  }
}

.remove-button {
  position: absolute;
  top: 12px;
  right: 12px;
  background: rgba(255, 255, 255, 0.95);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
  transition: all 0.3s ease;
  
  .dark & {
    background: rgba(0, 0, 0, 0.7);
    
    &:hover {
      background: rgba(0, 0, 0, 0.85);
    }
  }
}

.remove-button:hover {
  background: rgba(255, 255, 255, 1);
  transform: scale(1.1);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
}

.upload-area {
  width: 100%;
}

.upload-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px;
  min-height: 200px;
}

@media (max-width: 768px) {
  .upload-loading {
    padding: 30px;
    min-height: 150px;
  }
}

:deep(.n-upload) {
  width: 100%;
}

:deep(.n-upload-file-list) {
  display: none;
}

:deep(.n-card) {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
  transition: all 0.3s ease;

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
  }
}

</style>
